package relu.R.landscape;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import jfm.model.Types;
import jfm.model.Types.CropType;
import jfm.xml.XMLSyntaxException;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;

import jfm.mou.FarmerMOU;


public class GeographicLocationDistribution extends SocioEconomicDistribution {
	protected double rainFall=0;
	protected double[] soilWeights=new double[9]; // Soiltype weights
	protected double[] soilValues={0.5,0.75,1.0,1.25,1.5,1.75,2,2.25,2.5};
	private int county=1;
	private Map<String,HashMap<CropType,Double>> cropPrices=new HashMap<String,HashMap<CropType,Double>>();
	private String priceScenario=null;
	private double locationArea=0;
	protected String[] mouFiles=null;
	protected String[] xmlFiles=null;
	protected double[] mouFileWeights=null;
	protected double[] xmlFileWeights=null;

	public void setCropPricesForScenario(String scen){
		if ( cropPrices.containsKey(scen)){
			priceScenario=scen;
		} else {
			throw new Error("No price scenario named "+scen);
		}
	}
	
	
	public void setCropPriceScenarios(String csvFile){
		ArrayList<String> lines = readLines(csvFile);
		String[] header=lines.get(0).split(",");
		ArrayList<CropType> crops=new ArrayList<CropType>();
		try {
		for (int i=1;i<header.length;i++){
			crops.add(Types.xmlToCropType(header[i]));
		}} catch (XMLSyntaxException ex){
			throw new Error(ex.getMessage());
		}
		
		for(int i=1;i<lines.size();i++){
			String[] vals=lines.get(i).split(",");
			String scenario=vals[0];
			cropPrices.put(scenario, new HashMap<CropType,Double>());
			for(int j=1;j<vals.length;j++){
				cropPrices.get(scenario).put(crops.get(j-1),Double.parseDouble(vals[j]));
			}
		}
	}
	
	public void setSocialParameters(double[] weights,String[] names){
		mouFileWeights=new double[weights.length];
		this.mouFiles=new String[weights.length];
		for(int i=0;i<weights.length;i++){
			mouFileWeights[i]=weights[i];
			mouFiles[i]=names[i];
		}
	}
	
	public void setEconomicParameters(double[] weights,String[] names){
		xmlFileWeights=new double[weights.length];
		this.xmlFiles=new String[names.length];
		for(int i=0;i<weights.length;i++){
			xmlFileWeights[i]=weights[i];
			xmlFiles[i]=names[i];
		}
	}
	public void setLocationArea(double area){
		locationArea=area;
	}
	
	public void setGeographicParameters(double rf,double[] soilDistribution_,int county_){
		county=county_;
		rainFall=rf;
		if ( soilDistribution_.length!=soilWeights.length){
			throw new Error("Length mismatch. requires 9 soil types");
		}
		for(int s=0;s<soilWeights.length;s++){
			soilWeights[s]=soilDistribution_[s];
		}	
	}
	
	protected double[] sampleAreas(int n){
		double[] areas=new double[n];
		for(int i=0;i<areas.length;i++){
			areas[i]=locationArea*(1/(1.0*n));
		}
		return areas;
	}
	
	protected String[] sampleMOUs(int n){
		String[] mous=new String[n];
		for(int i=0;i<n;i++){
			mous[i]=mouFiles[0];
		}
		return mous;
	}
	protected String[] sampleXMLs(int n){
		String[] xmls=new String[n];
		for(int i=0;i<n;i++){
			xmls[i]=xmlFiles[0];
		}
		return xmls;
	}
	
	protected double[] sampleSoils(int n){
		double[] soils=new double[n];
		for( int i=0;i<n;i++){
			int soilbin = jfm.utils.JFMMath.chooseWeightedRandom(soilWeights, Landscape.rGen.nextDouble());
			soils[i]=soilValues[soilbin];
		}
		return soils;
	}
	
	public ArrayList<LSFarm> createRepresentativeFarms(int nFarms,NonSpatialLandscape ls){
		ArrayList<LSFarm> farms = new ArrayList<LSFarm>();
		double[] areas=sampleAreas(nFarms);
		String[] mouFiles=sampleMOUs(nFarms);
		String[] xmlFiles=sampleXMLs(nFarms);
		double[] soils = sampleSoils(nFarms);
		for(int i=0;i<nFarms;i++){
			FarmerMOU fmou = FarmerMOU.fromXML(mouFiles[i]);
			LSFarm theFarm = LSFarm.fromXML(xmlFiles[i], ls, null, areas[i]);
			theFarm.applyMOUToFarm(fmou);
			theFarm.setLocationInfo(soils[i], rainFall);
			farms.add(theFarm);
		//	System.out.println("Adding farm "+xmlFiles[i]+" "+areas[i]+" "+soils[i]+" "+rainFall);
		}
		return farms;
	}
	
	@Override
	public void sampleFarmer(LSFarm farm) {
		if ( priceScenario==null){
			throw new Error("Price scenario not yet set");
		}
		Map<CropType,Double> prices=cropPrices.get(priceScenario);
		for(CropType ct:prices.keySet()){
		//	System.out.println("Price "+prices.get(ct)+" "+ct);
			farm.setPriceForCrop(ct,prices.get(ct));
		}		
	}
	

	private static ArrayList<String> readLines(String fileName){
		ArrayList<String> lines = new ArrayList<String>();
		final BufferedReader reader;
		try {
			reader=new BufferedReader(new FileReader(fileName));
			String nextLine=reader.readLine();
			int lineCount=1;
			while(nextLine!=null){
				lines.add(nextLine);
				nextLine=reader.readLine();
			}
			
		} catch (FileNotFoundException ex){
			throw new Error(ex.getMessage());
		} catch (IOException ex){
			throw new Error(ex.getMessage());
		}
		return lines;
	}

}
